import { cloneDeep } from 'lodash-es'
import { useI18n } from '@/locales'
import { ConditionType } from '@/utils/index'
import { FormComponentKey } from '@/enums/componentKey'
import NumberCompareInput from './numberCompareInput.vue'
import NumberRangeSelect from './numberRangeSelect.vue'
import ColumnDataSelect from './ColumnDataSelect.vue'
import FixedAndDynamic from './fixedAndDynamic.vue'

const { t } = useI18n()

/** 全部的可选条件类型 */
const conditionTypeMap: Record<ConditionType, string> = {
  [ConditionType.IS_NULL]: t(`filterConditionType.${ConditionType.IS_NULL}`),
  [ConditionType.IS_NOT_NULL]: t(`filterConditionType.${ConditionType.IS_NOT_NULL}`),
  [ConditionType.BELONG]: t(`filterConditionType.${ConditionType.BELONG}`),
  [ConditionType.NOT_BELONG]: t(`filterConditionType.${ConditionType.NOT_BELONG}`),
  [ConditionType.CONTAIN]: t(`filterConditionType.${ConditionType.CONTAIN}`),
  [ConditionType.NOT_CONTAIN]: t(`filterConditionType.${ConditionType.NOT_CONTAIN}`),
  [ConditionType.PRE_IS]: t(`filterConditionType.${ConditionType.PRE_IS}`),
  [ConditionType.PRE_NOT_IS]: t(`filterConditionType.${ConditionType.PRE_NOT_IS}`),
  [ConditionType.END_IS]: t(`filterConditionType.${ConditionType.END_IS}`),
  [ConditionType.END_NOT_IS]: t(`filterConditionType.${ConditionType.END_NOT_IS}`),
  [ConditionType.BETWEEN]: t(`filterConditionType.${ConditionType.BETWEEN}`),
  [ConditionType.NOT_BETWEEN]: t(`filterConditionType.${ConditionType.NOT_BETWEEN}`),
  [ConditionType.EQUALS]: t(`filterConditionType.${ConditionType.EQUALS}`),
  [ConditionType.NOT_EQUALS]: t(`filterConditionType.${ConditionType.NOT_EQUALS}`),
  [ConditionType.DATE_GT]: t(`filterConditionType.${ConditionType.DATE_GT}`),
  [ConditionType.DATE_LT]: t(`filterConditionType.${ConditionType.DATE_LT}`),
  [ConditionType.GT]: t(`filterConditionType.${ConditionType.GT}`),
  [ConditionType.LT]: t(`filterConditionType.${ConditionType.LT}`),
  [ConditionType.GE]: t(`filterConditionType.${ConditionType.GE}`),
  [ConditionType.LE]: t(`filterConditionType.${ConditionType.LE}`),
  [ConditionType.IS_NULL_ARRAY]: t(`filterConditionType.${ConditionType.IS_NULL_ARRAY}`),
  [ConditionType.IS_NOT_NULL_ARRAY]: t(`filterConditionType.${ConditionType.IS_NOT_NULL_ARRAY}`),
  [ConditionType.EQ]: t(`filterConditionType.${ConditionType.EQ}`),
  [ConditionType.NE]: t(`filterConditionType.${ConditionType.NE}`)
}

/**
 *  通过key从对象中抽取子对象
 *
 * @param {object} obj
 * @param {string[]} keys
 * @return {*}  {object}
 */
const pickObjectByKeys = (obj: object, keys: string[]): object => {
  const result = {}
  keys.forEach(key => {
    if (obj[key]) {
      result[key] = obj[key]
    }
  })
  return result
}

// 带选项的组件可选的条件类型
const selectComponentConfig = pickObjectByKeys(conditionTypeMap, [
  ConditionType.IS_NULL,
  ConditionType.IS_NOT_NULL,
  ConditionType.EQUALS,
  ConditionType.NOT_EQUALS,
  ConditionType.CONTAIN,
  ConditionType.NOT_CONTAIN
])

// 组件可选的条件类型Map
export const ComponentConditionTypeMap: Record<FormComponentKey, object> = {
  [FormComponentKey.AlAddressFormPc]: pickObjectByKeys(conditionTypeMap, []),
  [FormComponentKey.AntdCascadeFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.BELONG,
    ConditionType.NOT_BELONG
  ]),
  [FormComponentKey.AntdCheckboxGroupFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.BELONG,
    ConditionType.NOT_BELONG,
    ConditionType.CONTAIN,
    ConditionType.NOT_CONTAIN
  ]),
  [FormComponentKey.AntdDatePickerFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.EQUALS,
    ConditionType.NOT_EQUALS,
    ConditionType.DATE_GT,
    ConditionType.DATE_LT
  ]),
  [FormComponentKey.AlDepartmentFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL
  ]),
  [FormComponentKey.AlDividerFormPc]: {},
  [FormComponentKey.AntdInputFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.EQUALS,
    ConditionType.NOT_EQUALS,
    ConditionType.CONTAIN,
    ConditionType.NOT_CONTAIN,
    ConditionType.PRE_IS,
    ConditionType.PRE_NOT_IS,
    ConditionType.END_IS,
    ConditionType.END_NOT_IS
  ]),
  [FormComponentKey.AntdTextareaFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.EQUALS,
    ConditionType.NOT_EQUALS,
    ConditionType.CONTAIN,
    ConditionType.NOT_CONTAIN,
    ConditionType.PRE_IS,
    ConditionType.PRE_NOT_IS,
    ConditionType.END_IS,
    ConditionType.END_NOT_IS
  ]),
  [FormComponentKey.AntdInputNumberFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.EQUALS,
    ConditionType.NOT_EQUALS,
    ConditionType.GT,
    ConditionType.LT,
    ConditionType.GE,
    ConditionType.LE,
    ConditionType.BETWEEN,
    ConditionType.NOT_BETWEEN
  ]),
  [FormComponentKey.AlContainerLayoutFormPc]: {},
  [FormComponentKey.AntdRadioGroupFormPc]: selectComponentConfig,
  [FormComponentKey.AntdRangePickerFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL
  ]),
  [FormComponentKey.AntdSelectFormPc]: selectComponentConfig,
  [FormComponentKey.AntdSelectCheckFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.BELONG,
    ConditionType.NOT_BELONG,
    ConditionType.CONTAIN,
    ConditionType.NOT_CONTAIN
  ]),
  [FormComponentKey.AlSerialNumberFormPc]: pickObjectByKeys(conditionTypeMap, [
   ConditionType.IS_NULL,
   ConditionType.IS_NOT_NULL,
   ConditionType.EQUALS,
   ConditionType.NOT_EQUALS,
   ConditionType.CONTAIN,
   ConditionType.NOT_CONTAIN,
   ConditionType.PRE_IS,
   ConditionType.PRE_NOT_IS,
   ConditionType.END_IS,
   ConditionType.END_NOT_IS,
 ]),
  [FormComponentKey.AlSubformFormPc]: {},
  [FormComponentKey.AntdTreeSelectFormPc]: selectComponentConfig,
  [FormComponentKey.AlUploadFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL
  ]),
  [FormComponentKey.AlImageUploadFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL
  ]),
  [FormComponentKey.AlUserFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL
  ]),
  // 数据自动更新数值类型
  [FormComponentKey.AlAutoDataInputNumberFormPc]: pickObjectByKeys(conditionTypeMap, [
    ConditionType.IS_NULL,
    ConditionType.IS_NOT_NULL,
    ConditionType.EQUALS,
    ConditionType.NOT_EQUALS,
    ConditionType.GT,
    ConditionType.LT,
    ConditionType.GE,
    ConditionType.LE
  ]),

  // TODO 流程审批状态 目前仅支持 已通过
  [FormComponentKey.AlProcessStatusFormPc]: pickObjectByKeys(conditionTypeMap, [
    // ConditionType.IN_PROCESS,
    ConditionType.APPROVED
    // ConditionType.REJECT,
    // ConditionType.REVOKE,
  ]),
  [FormComponentKey.AlRichTextFormPc]: [],
  [FormComponentKey.AlCorrelationQueryFormPc]: []
}
// 表单项组件对应使用的配置组件
export const optionComponentMapping: Partial<Record<ConditionType | `${FormComponentKey}|${ConditionType}`, string>> = {
  [ConditionType.BELONG]: 'ColumnDataSelect',
  [ConditionType.NOT_BELONG]: 'ColumnDataSelect',
  [ConditionType.CONTAIN]: 'TextInput',
  [ConditionType.NOT_CONTAIN]: 'TextInput',
  [ConditionType.IS_NULL]: '',
  [ConditionType.IS_NOT_NULL]: '',
  [ConditionType.PRE_IS]: 'TextInput',
  [ConditionType.PRE_NOT_IS]: 'TextInput',
  [ConditionType.END_IS]: 'TextInput',
  [ConditionType.END_NOT_IS]: 'TextInput',
  [ConditionType.EQUALS]: 'TextInput',
  [ConditionType.NOT_EQUALS]: 'TextInput',
  [ConditionType.GT]: 'NumberInput',
  [ConditionType.LT]: 'NumberInput',
  [ConditionType.GE]: 'NumberInput',
  [ConditionType.LE]: 'NumberInput',
  [ConditionType.BETWEEN]: 'NumberRangeSelect',
  [ConditionType.NOT_BETWEEN]: 'NumberRangeSelect',
  [ConditionType.DATE_GT]: 'DateSelect',
  [ConditionType.DATE_LT]: 'DateSelect',
  [ConditionType.IN_PROCESS]: '',
  [ConditionType.APPROVED]: '',
  [ConditionType.REJECT]: '',
  [ConditionType.REVOKE]: '',

  // 如果该类型组件配置比较特殊，可以通过组件key+ '|'+ ConditionType 来定义
  [`${FormComponentKey.AntdInputNumberFormPc}|${ConditionType.EQUALS}`]: 'NumberInput',
  [`${FormComponentKey.AntdInputNumberFormPc}|${ConditionType.NOT_EQUALS}`]: 'NumberInput',
  [`${FormComponentKey.AntdDatePickerFormPc}|${ConditionType.EQUALS}`]: 'DateSelect',
  [`${FormComponentKey.AntdDatePickerFormPc}|${ConditionType.NOT_EQUALS}`]: 'DateSelect',
  [`${FormComponentKey.AntdCheckboxGroupFormPc}|${ConditionType.CONTAIN}`]: 'ColumnDataSelect',
  [`${FormComponentKey.AntdCheckboxGroupFormPc}|${ConditionType.NOT_CONTAIN}`]: 'ColumnDataSelect',
  [`${FormComponentKey.AntdSelectCheckFormPc}|${ConditionType.CONTAIN}`]: 'ColumnDataSelect',
  [`${FormComponentKey.AntdSelectCheckFormPc}|${ConditionType.NOT_CONTAIN}`]: 'ColumnDataSelect'
}

export const componentMap = {
  ColumnDataSelect: {
    componentValue: ColumnDataSelect,
    defaultValue: [],
    props: {},
    validate: 'require'
  },
  NumberCompareInput: {
    componentValue: NumberCompareInput,
    defaultValue: {
      type: 'FIXED',
      value: null
    },
    props: {},
    validate: 'custom'
  },
  TextInput: {
    componentValue: 'AInput',
    defaultValue: '',
    props: {},
    validate: 'require'
  },
  NumberRangeSelect: {
    componentValue: NumberRangeSelect,
    defaultValue: {
      min: { type: 'GT', value: undefined },
      max: { type: 'LT', value: undefined }
    },
    props: {},
    validate: 'custom'
  },
  NumberInput: {
    componentValue: 'AInputNumber',
    defaultValue: undefined,
    props: {},
    validate: 'require'
  },
  NInput: {
    componentValue: 'AInputNumber',
    defaultValue: undefined,
    props: { step: 1, min: 0, precision: 0 },
    validate: 'require',
    label: 'N='
  },
  DateSelect: {
    componentValue: 'ADatePicker',
    defaultValue: undefined,
    props: { format: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD' },
    validate: 'require'
  },
  DateRangeSelect: {
    // componentValue: DateRangeSelect,
    defaultValue: {
      min: { type: 'GE', value: undefined },
      max: { type: 'LE', value: undefined }
    },
    props: {},
    validate: 'custom'
  },
  FixedAndDynamic: {
    componentValue: FixedAndDynamic,
    defaultValue: {
      type: 'FIXED',
      value: null
    },
    props: {},
    validate: 'custom'
  }
}

/**
 * 根据数据类型和条件类型获取表单组件
 * @param {*} type 字段类型
 * @param {*} conditionType 条件类型
 * @returns
 */
export function getComponent(componentKey: keyof typeof FormComponentKey, conditionType, showFixedAndDynamic = false) {
  let componentName = optionComponentMapping[conditionType]
  // 如果有非通用配置
  if (optionComponentMapping[`${componentKey}|${conditionType}`]) {
    componentName = optionComponentMapping[`${componentKey}|${conditionType}`]
  }
  if (showFixedAndDynamic) {
    return componentMap['FixedAndDynamic']
  }
  return componentMap[componentName]
}

/**
 * 根据数据类型和条件类型获取表单组件默认值
 * @param {*} type 字段类型
 * @param {*} conditionType 条件类型
 * @returns
 */
export function getComponentDefaultValue(componentKey, conditionType, showFixedAndDynamic = false) {
  const formComponent = getComponent(componentKey, conditionType, showFixedAndDynamic)
  if (formComponent) {
    return cloneDeep(formComponent.defaultValue)
  }
}

// 校验过滤条件树
export function handleCheckFilterConditionTree(conditionTree) {
  const { children, expression } = conditionTree

  // 如果存在子节点，则递归校验子节点
  if (children && children.length) {
    // 如果子节点中存在校验失败的条件，则直接返回false
    for (const treeNode of children) {
      const result = handleCheckFilterConditionTree(treeNode)
      if (!result) {
        return result
      }
    }
  } else {
    return handleCheckExpression(expression)
  }
  return true
}

// 校验过滤条件树节点中的表达式
function handleCheckExpression(expression) {
  const { filterType, filterCondition } = expression || {}

  // 如果不是合法的表达式，则校验失败
  if (!filterType || !filterCondition) {
    return false
  }

  // 校验条件过滤节点的表达式
  if (filterType === 'CONDITION') {
    const { filterColumnName, conditionType, value } = filterCondition

    if (filterColumnName && conditionType) {
      // 如果当前的条件类型需要value，则校验value是否为空
      let hasValue = value || value === 0
      if (value?.valueType) {
        hasValue = value?.value || value?.value === 0
      }
      if (
        ['IS_NULL', 'IS_NOT_NULL', 'IN_PROCESS', 'APPROVED', 'REJECT', 'REVOKE'].includes(conditionType) ||
        hasValue
      ) {
        return true
      }
    }

    return false
  }

  // 校验公式过滤节点中的表达式
  if (filterType === 'FORMULA') {
    const { formula } = filterCondition
    return Boolean(formula)
  }

  return false
}
